package com.kara.woodAgent.agent.wood.node;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.kara.woodAgent.agent.graph.Next;
import com.kara.woodAgent.agent.graph.Node;
import com.kara.woodAgent.agent.model.ModelProvider;
import com.kara.woodAgent.agent.tool.provider.ToolProvider;
import com.kara.woodAgent.agent.wood.context.WoodContext;
import com.kara.woodAgent.agent.wood.model.ExpectedMessage;
import com.kara.woodAgent.agent.wood.model.PlanResult;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.request.ResponseFormat;
import dev.langchain4j.model.chat.request.ResponseFormatType;
import dev.langchain4j.model.chat.response.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;


/**
 * @author tzy
 * @version 1.0
 * @project wood_agent
 * @description
 * @date 2025/6/10 10:00:07
 */

public class PlanNode implements Node<WoodContext> {


//	private List<SpecialAgentInfo> specialAgentInfoList;


//	public PlanningNode(List<SpecialAgentInfo> specialAgentInfoList) {
//		this.specialAgentInfoList = specialAgentInfoList;
//	}

    /**
     * #### 返回格式
     * 请以json 数组 作为你的返回，数组中的每个对象都包含以下的字段：
     * - id: 任务的唯一id (必须，从1开始，依次递增)
     * - content 子任务的详细描述 (必须，包括子任务的具体内容)
     * - agentName: 专项智能体的名称，对应 专项智能体的名称 字段 (必须)
     * - status: 固定为 dispatch 字符串 (必须)
     */
    private final ToolProvider.ToolServiceHolder toolProviderHolder;

    private final String systemPrompt = """
            #### 任务
            根据用户的任务描述 ，规划出一个任务列表。
            #### 注意
            1. 请创建简洁、可执行且步骤清晰的任务列表。重点关注关键里程碑，而非详细的子步骤。优化任务列表以确保清晰高效。
            #### 返回格式
            请以json对象作为你的返回，包含一个字段：
            	- plans: 任务列表 (必须),plans 是一个数组，每个元素是一个 任务对象
            &&&& 任务对象的格式
            	- id: 任务的唯一id (必须，从1开始，依次递增)
            	- content 子任务的详细描述 (必须，包括子任务的具体内容)
            	- status: 固定为 dispatch 字符串 (必须)
            """;
    @Autowired
    private ModelProvider modelProvider;

    public PlanNode(ToolProvider.ToolServiceHolder toolProviderHolder) {
        this.toolProviderHolder = toolProviderHolder;
    }

    @Override
    public Next execute(WoodContext context) {

        ExpectedMessage expectedMessage = context.getExpectedMessage();

        ChatLanguageModel chatModel = modelProvider.getChatModel("plan");
        List<ChatMessage> expectedWindows = expectedMessage.getExpectedWindows();
        if (StrUtil.isBlank(expectedMessage.getDisAgreeMsg())) {
            String userQuestion = context.getUserQuestion();
            expectedWindows.add(SystemMessage.from(systemPrompt));
            expectedWindows.add(UserMessage.from("用户输入: " + userQuestion));
        } else {
            UserMessage userMessage = UserMessage.from("不同意你的计划任务列表，原因是： " + expectedMessage.getDisAgreeMsg() + "\n" +
                    "#### 请按照要求重新生成任务列表");
            expectedWindows.add(userMessage);
            context.setPlans(null);
            expectedMessage.setDisAgreeMsg(null);
        }


        ChatRequest request = ChatRequest.builder()
                .messages(expectedWindows)
                .toolSpecifications(toolProviderHolder.toolSpecifications())
                .responseFormat(ResponseFormat.builder()
                        .type(ResponseFormatType.JSON).build())
                .build();
        ChatResponse chatResponse = chatModel.chat(request);

        AiMessage aiMessage = chatResponse.aiMessage();
        String text = aiMessage.text();

        PlanResult planResult = JSON.parseObject(text, PlanResult.class);

        expectedWindows.add(aiMessage);
//        String planLog = planResult.getPlans().stream().map(Plan::getMessage).collect(Collectors.joining("\n"));
//
//        ThinksPayload thinksPayload = ThinksPayload.of(planLog);
//        context.getChannel().thinksLog(thinksPayload);

        context.setPlans(planResult.getPlans());

        return Next.NextNode("planReview").step(aiMessage.toString());
    }


}
